23 #define foreach(x, v) for (typeof (v).begin() x=(v).begin(); x !=(v).end(); ++x)
24 #define For(i, a, b) for (int i=(a); i<(b); ++i)
25 #define D(x) cout << #x " is " << x << endl
29 bool isFunctor(string hash
){
31 if (n
<= 3) return false;
32 if (hash
[0] < 'a' || hash
[0] >'z') return false;
33 for (int i
= 1; i
< n
; i
++){
44 string
getFun(string hash
){
47 for (int i
= 0; i
< n
; i
++){
48 if (hash
[i
] == '(') break;
53 vector
<string
> getArgs (string hash
){
60 for (int i
= 0; i
< n
- 1; i
++){
65 if (hash
[i
] == ',' && p
.size() == 0){
69 if(paren
) arg
+= hash
[i
];
79 if (i
== n
- 2) args
.push_back(arg
);
84 bool isVar(string hash
){
85 if(hash
[0] < 'A' || hash
[0] > 'Z') return false;
89 bool isConst(string hash
){
90 if (isVar(hash
) || isFunctor(hash
)) return false;
94 bool occurs(string var
, string hash
){
95 if (hash
.find(var
) == string::npos
) return false;
99 vector
<pair
<string
, string
> > unify (string hash1
, string hash2
){
100 vector
<pair
<string
, string
> > ans
;
101 // Verify if they already unify
102 if (!doUnify
) return ans
;
104 int n1
= hash1
.size();
105 int n2
= hash2
.size();
106 if (n1
== 0 || n2
== 0) return ans
;
108 if (isFunctor(hash1
) and isFunctor(hash2
)){
109 if (getFun(hash1
) == getFun(hash2
)){
111 vector
<string
> v1
= getArgs(hash1
);
112 vector
<string
> v2
= getArgs(hash2
);
113 if (v1
.size() != v2
.size()){
117 for (int i
= 0; i
< v1
.size(); i
++){
118 vector
<pair
<string
, string
> > vect
= unify(v1
[i
], v2
[i
]);
119 if (!doUnify
) return ans
;
120 for (int j
= 0; j
< vect
.size(); j
++){
121 ans
.push_back(vect
[j
]);
129 // Unify variable and constant
130 if(isVar(hash1
) && isConst(hash2
)){
131 ans
.push_back(make_pair(hash1
, hash2
));
134 if(isVar(hash2
) && isConst(hash1
)){
135 ans
.push_back(make_pair(hash2
, hash1
));
138 // Unify variable and variable/ functor
139 if(isVar(hash1
) and !isConst(hash2
)){
140 if (occurs(hash1
, hash2
)){
141 if(hash1
== hash2
) return ans
;
145 ans
.push_back(make_pair(hash1
, hash2
));
148 if(isVar(hash2
) and !isConst(hash1
)){
149 if (occurs(hash2
, hash1
)){
153 ans
.push_back(make_pair(hash2
, hash1
));
156 // Unify two constants
157 if (isConst(hash1
) && isConst(hash2
)){
158 if(hash1
!= hash2
) doUnify
= false;
161 // Unify a constant and a functor
167 string
replce(string oc
, string str
, string rep
){
168 while(str
.find(oc
) != string::npos
){
169 int pos
= str
.find(oc
);
170 str
.replace(pos
, oc
.size(), rep
);
175 vector
<pair
<string
, string
> > make_replacements( vector
<pair
<string
,string
> > v
){
177 for (int i
= 0; i
< n
; i
++){
178 string var
= v
[i
].first
;
179 string rep
= v
[i
].second
;
180 for (int j
= 0; j
< n
; j
++){
181 if (j
== i
) continue;
182 //If the variable is in the first term
183 if (v
[j
].first
== var
){
184 string second
= v
[j
].second
;
186 v
.erase (v
.begin()+j
);
187 //Erase it and add the unification of the other varibles
188 vector
<pair
<string
, string
> > unif
= unify(rep
, second
);
189 for (int k
= 0; k
< unif
.size(); k
++){
190 v
.push_back(unif
[k
]);
192 }else if(!isVar(rep
)){
199 //If the variable is in the second term
200 if (occurs(var
, v
[j
].second
) ){
201 if (occurs(v
[j
].first
, rep
)){
205 v
[j
].second
= replce(var
, v
[j
].second
, rep
);
221 vector< pair<string, string> > v = unify("f(f(X),Z)","f(f(Y), c)");
222 for (int i = 0; i < v.size(); i++){
223 printf("%s / %s\n", v[i].first.c_str(), v[i].second.c_str());
226 while (cin
>> name
>> n
){
229 for (int i
= 0; i
< n
; i
++) cin
>> hash
[i
];
231 vector
<pair
<string
, string
> > unifiers
[n
- 1];
233 for (int i
= 0; i
< n
- 1; i
++){
235 unifiers
[i
] = unify(hash
[i
], hash
[i
+1]);
236 //Make replacements with unifiers
237 if (doUnify
) unifiers
[i
] = make_replacements(unifiers
[i
]);
240 /*for (int i = 0; i < n - 1; i++){
241 int n = unifiers[i].size();
242 printf("El unificador %d es:\n", i);
243 for (int j = 0; j < n; j++){
244 printf("%s / %s\n", (unifiers[i][j].first).c_str(), (unifiers[i][j].second).c_str());
248 vector
<pair
<string
, string
> > joint
= unifiers
[0];
249 for (int i
= 1; i
< n
- 1; i
++){
250 for (int k
= 0; k
< unifiers
[i
].size(); k
++){
251 for (int j
= 0; j
< joint
.size(); j
++){
253 if (occurs(unifiers
[i
][k
].first
, joint
[j
].second
)){
254 if(occurs(joint
[j
].first
, unifiers
[i
][k
].second
) ){
258 joint
[j
].second
= replce( unifiers
[i
][k
].first
, joint
[j
].second
, unifiers
[i
][k
].second
);
263 for (int j
= 0; j
< joint
.size(); j
++){
264 if(unifiers
[i
][k
].first
== joint
[j
].first
){
265 unifiers
[i
].erase(unifiers
[i
].begin()+k
);
271 for (int k
= 0; k
< unifiers
[i
].size(); k
++){
272 joint
.push_back(unifiers
[i
][k
]);
274 int n
= joint
.size();
275 /*printf("El unificador %d conjunto es:\n", i);
276 for (int j = 0; j < n; j++){
277 printf("%s / %s\n", (joint[j].first).c_str(), (joint[j].second).c_str());
283 printf("%s is a Starflyer agent\n", name
.c_str());
285 printf("analysis inconclusive on %s\n", name
.c_str());